package com.spring.proxy.classloader.gencode;  
  
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.springframework.asm.ClassWriter;
import org.springframework.asm.MethodVisitor;
import org.springframework.asm.Opcodes;  
public class CglibGenerator {  
  
    public static void main(String[] args) throws IOException {  
    	generateCode();
    	run();  
    }

	private static void generateCode() throws FileNotFoundException, IOException {
        ClassWriter classWriter = new ClassWriter(0);  
        // 通过visit方法确定类的头部信息  
        classWriter.visit(Opcodes.V1_7,// java版本  
                Opcodes.ACC_PUBLIC,// 类修饰符  
                "Programmer", // 类的全限定名  
                null, "java/lang/Object", null);  
          
        //创建构造函数  
        MethodVisitor mv = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);  
        mv.visitCode();  
        mv.visitVarInsn(Opcodes.ALOAD, 0);  
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>","()V");  
        mv.visitInsn(Opcodes.RETURN);  
        mv.visitMaxs(1, 1);  
        mv.visitEnd();  
          
        // 定义code方法  
        MethodVisitor methodVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "code", "()V",  
                null, null);  
        methodVisitor.visitCode();  
        methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out",  
                "Ljava/io/PrintStream;");  
        methodVisitor.visitLdcInsn("I'm a Programmer,Just Coding.....");  
        methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println",  
                "(Ljava/lang/String;)V");  
        methodVisitor.visitInsn(Opcodes.RETURN);  
        methodVisitor.visitMaxs(2, 2);  
        methodVisitor.visitEnd();  
        classWriter.visitEnd();   
        // 使classWriter类已经完成  
        // 将classWriter转换成字节数组写到文件里面去  
        byte[] data = classWriter.toByteArray();  
        File file = new File("D://Programmer.class");  
        FileOutputStream fout = new FileOutputStream(file);  
        fout.write(data);  
        fout.close();
	} 
    
    public static void run() throws IOException {
		// 读取本地的class文件内的字节码，转换成字节码数组
		File file = new File(".");
		InputStream input = new FileInputStream("D://Programmer.class");
		byte[] result = new byte[1024];

		int count = input.read(result);
		// 使用自定义的类加载器将 byte字节码数组转换为对应的class对象
		MyClassLoader loader = new MyClassLoader();
		Class clazz = loader.defineMyClass(result, 0, count);
		// 测试加载是否成功，打印class 对象的名称
		System.out.println(clazz.getCanonicalName());

		// 实例化一个Programmer对象

		try {
			Object o = clazz.newInstance();
			// 调用Programmer的code方法
			clazz.getMethod("code", null).invoke(o, null);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}